using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Galplay {

  public class PlayQueue {
    GameScenePlayer player { get; }
    Queue<GalScript> queue;
    public GalScene Scene => player.Scene;
    public GalScriptPack Events => player.Events;
    // 这个Queue的开始ScriptIndex
    public int StartIndex { get; set; }
    // 这个Queue执行完之后，要执行的下一个ScriptIndex
    public int NextIndex { get; set; }
    // 是否已经结束
    public bool IsEnd { get; set; }

    public PlayQueue(GameScenePlayer player) {
      this.player = player;
      this.queue = new Queue<GalScript>();
    }

    public void ResetStart(int start_point = 0) {
      Clear();
      NextIndex = start_point;
      IsEnd = false;
    }

    public void SetEnd() {
      IsEnd = true;
    }

    public void Clear() {
      queue.Clear();
    }

    public void Add(GalScript script) {
      queue.Enqueue(script);
    }

    public void RunScript(GalScript script) {
      player.RunScript(script);
    }

    /// <summary>
    /// 在Process的跳动的时候，需要执行的项目。
    /// 这个Jump还是有一些小问题。比如说，设置的Picture，可能之后就没有命令取消掉，就会一直在。
    /// </summary>
    /// <param name="process"></param>
    public void Jump(float process) {
      int index = (int)(Scene.Scripts.Count * process);

      player.imageManager.HideAll();

      // 获得最后一个文本和背景
      var bg = Scene.GetLastBefore(index, ScriptType.BG);
      RunScript(bg);

      // 重置开始状态
      ResetStart(index);
    }

    // 将项目全部执行
    public void Flush(){
      if (queue.Count > 0){
        var script = queue.Dequeue();
        RunScript(script);
      }
    }

    // 从项目中提取需要执行的脚本到队列
    public void PickScript() {
      // 如果已经结束，那么无法提取脚本，需要手动设置
      if (IsEnd) {
        return;
      }

      int safe_guard = 0;

      while (true) {
        // 得到指定位置的脚本
        var script = player.Scene.GetLine(NextIndex);
        // 步进下一个脚本
        NextIndex++;

        // 如果已经无法获得脚本，那么退出
        if (script == null) {
          SetEnd();
          return;
        }

        // 寻找到下一个Text，执行
        if (script.Type == ScriptType.Text) {
          player.PlayText((ScriptText)script);
          return;
        }

        // 如果是命令，则填充命令
        if (script.Type == ScriptType.Event) {
          Fill((ScriptEvent)script);
        } else {
          // 如果是其它的命令，直接增加
          Add(script);
        }

        if (safe_guard++ > 1000) {
          break;
        }
      }

    }

    private void Fill(ScriptEvent script, int layer = 0) {
      // SafeGuard，避免有Script设置出现问题，导致重复引用。最多10层引用
      if (layer > 10) {
        return;
      }

      // 从项目中获得Event
      var list = Events.Get(script.EventID);
      // 如果不存在，则返回
      if (list == null) { return; }

      // 依次填充
      foreach (var item in list.Scripts) {
        // 如果是Event，则再进行递归填充
        if (item.Type == ScriptType.Event) {
          Fill((ScriptEvent)item, layer + 1);
        } else {
          Add(item);
        }
      }
    }

    internal GalScript Pop() {
      if (queue.Count == 0) { return null; }
      return queue.Dequeue();
    }
  }
}